fix: send createSession 201 only after the transaction commits - #1461
Merged
KaranUnique merged 238 commits intoAug 8, 2026
Merged
Conversation
…dmap Integrated ai powered project roadmap
…-64423 fix: code quality and safety improvements
…-37396 fix: code quality and safety improvements
…ats-checker feat: enhance AI Resume Analyzer with ATS compatibility insights
…ral-interview-coach feat: implement AI Behavioral Interview Coach
…n-calendar feat: add personalized interview preparation calendar
…uestion-collections feat: add interview question bookmark collections page
…preparation-certificates feat: add interview preparation achievement certificates page
Automated dependency upgrade by OrbisAI Security
…dency [Bug]: Missing Dependency in useMemo within BookmarkCollections
roadmapRoutes.js defines the full roadmap API (CRUD + task toggle, protected, rate-limited) but was never registered in server.js, so every frontend call to /api/roadmaps* returned 404. Mount the router at /api/roadmaps to match the frontend API_PATHS.ROADMAP entries. Verified by booting the server: /api/roadmaps now returns 401 (auth required) instead of 404.
Addresses CodeRabbit review comment on PR Canopus-Labs#1248. Versions 9.0.2–9.0.4 include STARTTLS pre-TLS buffer discarding (RFC 3207 §6 capability injection fix), correct TLS handshake over user-provided sockets, and SMTP parsing/socket lifecycle hardening. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…HSA-p6gq-j5cr-w38f-nodemailer fix: upgrade nodemailer to 9.0.1 (GHSA-p6gq-j5cr-w38f)
ci: add automated stale issue and PR workflow
…roadmap-routes fix: mount roadmap routes so the Project Roadmap feature stops 404ing
…iew-preparation-snapshot feat: add AI interview preparation snapshot
…alized-interview-preparation-tips feat: add AI personalized interview preparation tips
…iew-preparation-milestone-calendar feat: add AI interview preparation milestone calendar
…mastery-progress-bar feat: add AI topic mastery progress bar
…iew-preparation-habit-tracker feat: add AI interview preparation habit tracker
The success response and 4xx validation returns were issued inside the withTransaction callback, so a 201 could reach the client before the commit finished (phantom success on rollback), and returning res inside the callback resolved it as a commit instead of an abort. Move validation ahead of the transaction, return the created session from the callback, and send the response only after withTransaction resolves. Closes Canopus-Labs#1442
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
createSession(backend/controllers/sessionController.js) runs all writes insidemongoSession.withTransaction(async () => { ... }), but:res.status(201).json(...)is sent inside the callback — before Mongoose commits. If the commit subsequently fails (network error, replica-set failover, duplicate key on a concurrent write), the client already got a201+ full session object while the transaction was rolled back: a phantom success.return res.status(400)inside the callback. Mongoose'swithTransactioncommits based on the callback's return value, so returning an Express response object commits instead of aborting — the opposite of the code's obvious intent.Fix
role/experience/MAX_SESSIONSchecks now run first and return 4xx from the outer handler, never from inside the callback.res.*out of the callback — the callback returns the created session, andres.status(201).json(...)is sent only afterwithTransactionresolves (i.e. after commit).SESSION_LIMIT_REACHEDthrow is replaced by an early 400 return ahead of the transaction.endSession()stays infinally, guarded for the pre-transaction validation paths.Files changed
backend/controllers/sessionController.js— restructuredcreateSession.backend/tests/sessionController.create.transaction.unit.test.js— tests for 400s without starting a transaction, no 201 on commit failure, and 201 only after commit.Testing
npx vitest run tests/sessionController.create.transaction.unit.test.js— 5/5 passing.Closes #1442